﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Xml.Linq;
using EDMDesigner.Business.CSDL.Association;
using EDMDesigner.Business.CSDL.Type.Complex;
using EDMDesigner.Business.CSDL.Type.Entity;
using EDMDesigner.Designer.Controls;
using EDMDesigner.Designer.Controls.CSDLType;
using EDMDesigner.Designer.Controls.Util;
using EDMDesigner.EdmxRW;
using EDMDesigner.Designer.Resources;
using EDMDesigner.UIBusiness;
using EDMDesigner.UIBusiness.CSDL.Property;
using EDMDesigner.UIBusiness.CSDL.Type;

namespace EDMDesigner.Designer
{
    public partial class EDMDesignerWindow : Window
    {
        private const string ODP_NAME = "odp";

        private TabItem _toolBoxCurrentTabItem;

        public EDMDesignerWindow()
        {
            Configuration.Instance.EdmxPath = Environment.GetCommandLineArgs()[1];
            XElement edmxElement = null;
            EDMController.ReadMoreAction = edmxElt => edmxElement = edmxElt;
            InitializeComponent();
            EntityTypeDesigner.Init = true;
            DesignerViewRW.Reader.Read(EDMView, edmxElement.Element("DesignerViews"), entityType => new EntityTypeDesigner(entityType), complexType => new ComplexTypeDesigner(complexType));
            EntityTypeDesigner.Init = false;
            InitCommandBinding();

            toolBoxTabControl.SelectionChanged +=
                delegate
                {
                    if (_toolBoxCurrentTabItem != toolBoxTabControl.SelectedItem)
                    {
                        _toolBoxCurrentTabItem = (TabItem)toolBoxTabControl.SelectedItem;
                        if (toolBoxTabControl.SelectedItem == propertiesTabItem)
                            propertiesGrid.Bind(Selection);
                        else if (toolBoxTabControl.SelectedItem == mappingTabItem)
                        {
                            var entityType = Selection as EntityType;
                            if (entityType != null)
                                mapping.BindEntityType(entityType);
                            else
                                mapping.BindAssociation(Selection as Association);
                        }
                    }
                };

            designerTab.CreateNewItemControl = dv =>
                {
                    var designerView = (DesignerView)dv;
                    var sv = new ScrollViewer { HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden, VerticalScrollBarVisibility = ScrollBarVisibility.Hidden };
                    var dc = DesignerCanvas.GetDesignerCanvas(EDMView, designerView);
                    dc.AllowDrop = true;
                    sv.Content = dc;
                    designerTab.SelectionChanged += delegate
                    {
                        sv.Content = DesignerCanvas.GetDesignerCanvas(EDMView, designerView);
                    };
                    return sv;
                };

            Action<Wpf.Controls.TabItem> renameCurrentItem = tabItem =>
            {
                var renameCommand = new RoutedCommand();
                var contextMenu = new ContextMenu();
                contextMenu.Items.Add(new MenuItem { Command = renameCommand, Header = DesignerTabControlResources.Rename, InputGestureText = "F2" });
                tabItem.ContextMenu = contextMenu;
                Action edit = () =>
                    {
                        var editableTextBlock = VisualTreeHelperUtil.GetControlsDecendant<EditableTextBlock>(tabItem).FirstOrDefault();
                        if (editableTextBlock != null)
                            editableTextBlock.Edit();
                    };
                CommandBindings.Add(new CommandBinding(renameCommand,
                    delegate
                    {
                        edit();
                    },
                    (commandSender, commandEventArgs) => commandEventArgs.CanExecute = designerTab.GetTabItem(designerTab.SelectedIndex) == tabItem
            ));
                tabItem.KeyDown += (sender, e) =>
                    {
                        if (e.Key == Key.F2)
                        {
                            edit();
                            e.Handled = true;
                        }
                    };
            };

            Loaded += delegate
                {
                    foreach (var tabItem in designerTab.GetTabItems())
                        renameCurrentItem(tabItem);
                };

            designerTab.NewTabItem += delegate
                {
                    renameCurrentItem(designerTab.GetTabItem(designerTab.Items.Count - 1));
                };
        }

        private EDMView EDMView
        {
            get
            {
                return (EDMView)((ObjectDataProvider)FindResource(ODP_NAME)).Data;
            }
        }

        public DesignerView CurrentDesignerView
        {
            get { return CurrentDesignerSurface.DesignerView; }
            set { designerTab.SelectedValue = value; }
        }

        private DesignerCanvas CurrentDesignerSurface
        {
            get
            {
                return VisualTreeHelperUtil.GetControlsDecendant<DesignerCanvas>((ScrollViewer)designerTab.ItemsControls[designerTab.SelectedValue]).First();
            }
        }

        private void designerTab_NewTabItem(object sender, Wpf.Controls.NewTabItemEventArgs e)
        {
            EDMView.DesignerViews.Add(DesignerView.NewView());
        }

        protected override void OnMouseUp(MouseButtonEventArgs e)
        {
            base.OnMouseUp(e);
            CurrentDesignerSurface.SelectFromRectangle();
        }

        protected override void OnPreviewKeyDown(KeyEventArgs e)
        {
            base.OnPreviewKeyDown(e);
            if (!(e.OriginalSource is TextBox))
                switch (e.Key)
                {
                    case Key.Back:
                        CurrentDesignerSurface.OnBackSpaceDown();
                        e.Handled = true;
                        break;
                    case Key.Delete:
                        if (!VisualTreeHelperUtil.IsAscendant(toolBoxTabControl, (DependencyObject)e.OriginalSource))
                            e.Handled = CurrentDesignerSurface.OnDeleteDown(e.OriginalSource);
                        break;
                    case Key.Escape:
                        CurrentDesignerSurface.OnEscapeDown();
                        e.Handled = true;
                        break;
                }
        }

        private void DesignerTab_MouseLeave(object sender, MouseEventArgs e)
        {
            CurrentDesignerSurface.UITypeToAdd = null;
        }

        private object _selection;
        public object Selection
        {
            get { return _selection; }
            set
            {
                if (_selection == value)
                    return;
                _selection = value;
                EntityType valueEntityType;
                if (toolBoxTabControl.SelectedItem == propertiesTabItem && propertiesGrid != null)
                    propertiesGrid.Bind(value);
                else if (toolBoxTabControl.SelectedItem == mappingTabItem && mapping != null)
                {
                    Association association;
                    if (!((valueEntityType = value as EntityType) == null || mapping.EntityType == valueEntityType))
                        mapping.BindEntityType(valueEntityType);
                    else if (value is ComplexType)
                        mapping.BindEntityType(null);
                    else if (value == null)
                        mapping.BindEntityType(null);
                    else if ((association = value as Association) != null)
                        mapping.BindAssociation(association);
                }
            }
        }
        public void ShowPropertiesTab()
        {
            toolBoxTabControl.SelectedItem = propertiesTabItem;
        }
        public void ShowPropertiesTab(IUIType type)
        {
            Selection = type.BusinessInstance;
            ShowPropertiesTab();
        }
        public void ShowPropertiesTab(UIProperty property)
        {
            Selection = property.BusinessInstance;
            ShowPropertiesTab();
        }

        public void ShowMappingTab()
        {
            toolBoxTabControl.SelectedItem = mappingTabItem;
        }
        public void ShowMappingTab(IUIType type)
        {
            Selection = type.BusinessInstance;
            ShowMappingTab();
        }

        private void EntityTypesListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            SelectEntityTypeFromListView();
        }
        private void SelectEntityTypeFromListView()
        {
            if (entityTypesListView.SelectedItems.Count == 1)
                Selection = ((UIEntityType)entityTypesListView.SelectedValue).BusinessInstance;
        }
        private void HierarchyFilterTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            SelectEntityTypeFromTreeView();
        }
        private void SelectEntityTypeFromTreeView()
        {
            var value = ((UIEntityType)hierarchyFilterTreeView.SelectedValue);
            Selection = value == null ? null : value.BusinessInstance;
        }
        private void ComplexTypesListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            SelectComplexTypeFromListView();
        }
        private void SelectComplexTypeFromListView()
        {
            if (complexTypesListView.SelectedItems.Count == 1)
                Selection = ((UIComplexType)complexTypesListView.SelectedValue).BusinessInstance;
        }
        private void EntityTypesListView_GotFocus(object sender, RoutedEventArgs e)
        {
            SelectEntityTypeFromListView();
        }
        private void HierarchyFilterTreeView_GotFocus(object sender, RoutedEventArgs e)
        {
            SelectEntityTypeFromTreeView();
        }
        private void ComplexTypesListView_GotFocus(object sender, RoutedEventArgs e)
        {
            SelectComplexTypeFromListView();
        }

        private void SaveButton_Click(object sender, RoutedEventArgs e)
        {
            Save();
        }

        private void Save()
        {
            Writer.Write(EDMView.EDM, DesignerViewRW.Writer.Write(EDMView)).Save(Configuration.Instance.EdmxPath);
        }
    }
}
